<?php
/**
 *
 * @category   babel 
 * @package    BABEL
 * @author     Hannes Magnusson <hannes.magnusson@gmail.com>
 * @copyright  2008 Team babel
 * @license    LGPL
 */

class BabelLanguageFile implements Iterator {
	const REQUIRED = 0x01;
	const OPTIONAL = 0x02;
	private $r;

	public static function createFile($stream) {
		$content = stream_get_contents($stream);
		$dom = new DOMDocument;
		if (!$dom->loadXML($content)) {
			throw new Exception("Invalid XML file");
		}

		$r = new XMLReader;
		$r->XML($content);
		fclose($stream);
		return new self($r);
	}
	private function __construct($r, array $attrs = null) {
		$this->r = $r;
		if ($attrs === null) {
			do {
				$r->read();
			} while($r->nodeType != XMLReader::ELEMENT || $r->name != "file");

			$attrs = $this->getAttributes($r, $r->name);
		}
		$this->attrs = $attrs;
	}

	private function getAttributes($r, $elm) {
		static $entryAttributes = array(
			"name"        => self::REQUIRED,
			"revision"    => self::REQUIRED,
			"type"        => self::OPTIONAL,
			"context"     => self::OPTIONAL,
		);
		static $fileAttributes = array(
			"name"        => self::REQUIRED,
			"lang"        => self::REQUIRED,
			"revision"    => self::REQUIRED,
		);

		$attrs = array();
		if ($r->hasAttributes) {
			$r->moveToFirstAttribute();
			do {
				$attrs[$r->localName] = $r->value;
			} while ($r->moveToNextAttribute());
			$r->moveToElement();
		} else {
			debug_print_backtrace();
		}

		$elmattrs = $elm === "entry" ? $entryAttributes : $fileAttributes;
		foreach($elmattrs as $attr => $cond) {
			if (!isset($attrs[$attr])) {
				if ($cond === self::REQUIRED) {
					throw new Exception("Element doesn't contain all required elements ($attr)");
				} else {
					$attrs[$attr] = null;
				}
			}
		}

		return $attrs;

	}
	public function key() {
		return (string)$this->current;
	}
	public function current() {
		return $this->current;
	}
	public function valid() {

		$r = $this->r;
		while($r->read()) {
			switch ($r->nodeType) {
			case XMLReader::ELEMENT:

				$attrs = $this->getAttributes($r, $r->name);
				switch($r->name) {
				case "entry":
					$this->current = new BabelConstant($attrs["name"], $r->readString(), $attrs["revision"], $attrs);

					// Jump over the end element
					$r->read();
					return true;
					break;

				case "file":
					$this->current = new self($r, $attrs);
					return true;
					break;
				}
				break;
			case XMLReader::END_ELEMENT:
				switch($r->name) {
				case "file":
					return false;
					break;
				}
			}
		}
		return false;
	}
	public function next() {
	}
	public function rewind() {
	}

	public function __get($var) {
		if (isset($this->attrs[$var])) {
			return $this->attrs[$var];
		}
		return null;
	}
	public function __call($var, $args) {
		if (strncasecmp($var, "get", 3) === 0) {
			return $this->{strtolower(substr($var, 3))};
		}
		throw new Exception("Unknown property requested");
	}
	public function __toString() {
		return $this->getName();
	}
	public function getMeta() {
		return $this->attrs;
	}
}

